package com.disapand.strongarmy.exception

import cn.dev33.satoken.exception.*
import com.disapand.strongarmy.enum.*
import com.disapand.strongarmy.vo.*
import org.springframework.dao.*
import org.springframework.web.*
import org.springframework.web.bind.*
import org.springframework.web.bind.annotation.*
import org.springframework.web.multipart.support.*
import java.util.*
import javax.servlet.http.*
import javax.validation.*

/**
 * 全局异常拦截器
 *
 * @auth disapand
 * @date 2021/10/12 - 22:29 - 星期二
 *
 */
@RestControllerAdvice
class SaExceptionHandle {

    /**
     * 捕获 sa-token 鉴权失败异常进行处理
     *
     * @param exception
     * @return
     */
    @ExceptionHandler(NotLoginException::class)
    fun saTokenException(exception: NotLoginException): ResponseVO {
        return when(exception.type) {
            NotLoginException.NOT_TOKEN -> ResponseVO(ResponseCode.NOT_TOKEN, "账号未登录，请登录后再进行操作")
            NotLoginException.INVALID_TOKEN -> ResponseVO(ResponseCode.INVALID_TOKEN, "token 非法，请确认后再试")
            NotLoginException.TOKEN_TIMEOUT -> ResponseVO(ResponseCode.TOKEN_TIMEOUT, "登录已过期，请重新登录")
            NotLoginException.BE_REPLACED -> ResponseVO(ResponseCode.BE_REPLACED, "账号已在其他地方登录")
            NotLoginException.KICK_OUT -> ResponseVO(ResponseCode.KICK_OUT, "账号已被踢下线")
            else -> ResponseVO(ResponseCode.FAIL, "未知异常")
        }
    }

    /**
     * 捕获系统自定义异常
     *
     * @param exception
     * @return
     */
    @ExceptionHandler(SaException::class)
    fun exceptionHandle(exception: SaException): ResponseVO {
        return ResponseVO(exception.responseCode, exception.data)
    }

    /**
     * 请求方法不支持
     *
     * @param request
     * @param exception
     */
    @ExceptionHandler(HttpRequestMethodNotSupportedException::class)
    fun methodNotSupportException(
        request: HttpServletRequest,
        exception: HttpRequestMethodNotSupportedException
    ): ResponseVO {
        return ResponseVO(ResponseCode.METHOD_NOT_SUPPORT,
            "当前发起请求的方法是[${exception.method}], 接口[${request.requestURI}]只支持${Arrays.toString(exception.supportedMethods)}方法")
    }

    /**
     * requestParameter 传参方式参数缺失
     *
     * @param exception
     * @return
     */
    @ExceptionHandler(MissingServletRequestParameterException::class)
    fun missingRequestParameterException(exception: MissingServletRequestParameterException): ResponseVO {
        val result = mapOf(exception.parameterName to "参数不能为空")
        return ResponseVO(ResponseCode.ERROR_PARAMS, result)
    }

    /**
     * requestPart 传参方式参数缺失
     *
     * @param exception
     * @return
     */
    @ExceptionHandler(MissingServletRequestPartException::class)
    fun missingRequestPartException(exception: MissingServletRequestPartException): ResponseVO {
        val result = mapOf(exception.requestPartName to "参数不能为空")
        return ResponseVO(ResponseCode.ERROR_PARAMS, result)
    }

    /**
     * 参数校验错误
     *
     * @param exception
     * @return
     */
    @ExceptionHandler(ConstraintViolationException::class)
    fun constraintViolationException(exception: ConstraintViolationException): ResponseVO {
        val constraintViolations = exception.constraintViolations
        val iterator = constraintViolations.iterator()
        val msgList: MutableMap<String, String> = mutableMapOf()
        while (iterator.hasNext()) {
            val next = iterator.next()
            val path = next.propertyPath
            val splitStr = path.toString().split(".")
            val property = splitStr[splitStr.size - 1]
            msgList[property] = next.messageTemplate
        }
        return ResponseVO(ResponseCode.ERROR_PARAMS, msgList)
    }

    /**
     * sql 执行异常
     *
     * @param exception
     * @return
     */
    @ExceptionHandler(DataAccessException::class)
    fun dataAccessException(exception: DataAccessException): ResponseVO {
        return ResponseVO(ResponseCode.DATA_EXIST, "已存在相同数据")
    }

    // @ExceptionHandler(Exception::class)
    // fun handleException(exception: Exception): ResponseVO {
    //     return ResponseVO.ofError("未知异常")
    // }
}